#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

typedef unsigned char byte;

char MAGIC[] = {'H','1','d','e'};

void usage(char*name) {
	fprintf(stderr,"Usage:\n%s file1\n",name);
	fprintf(stderr,"Extract hidden file from file1 and send bytes to standard out.\n");
	exit(1);
}

void exitNoHiddenFileError(char*file, char *reason) {
	fprintf(stderr,"No hidden file found in %s:%s\n",file,reason);
	exit(2);
}
void exitError(char*file,char *action) {
	perror("Exiting");
	fprintf(stderr,"Error while %s on file %s.\n",action,file);
	exit(3);	
}

int main(int argc, char** argv) {
	if(argc != 2) usage(argv[0]);
   int file;
   byte buffer [4096];
   byte integer [4];
   int filesize = 0;
   int i = 0;
   file = open ( argv [ 1 ], O_RDWR | O_APPEND );
   if ( file == -1 )
   {
      exitError ( argv [ 1 ], "opening" );
   }
   off_t offset = lseek ( file, -4, SEEK_END );
   if ( offset == -1 )
   {
      exitError ( argv [ 1 ], "seeking" );
   }
   ssize_t num_bytes = read ( file, ( void* ) buffer, 4 );
   if ( num_bytes < 4 )
   {
      exitNoHiddenFileError( argv [ 1 ], "Identifier missing" );
   }
   if (( buffer [0] != 'H' ) ||
       ( buffer [1] != '1' ) ||
       ( buffer [2] != 'd' ) ||
       ( buffer [3] != 'e' ))
   {
      exitNoHiddenFileError( argv [ 1 ], "Identifier missing" );
   }
   offset = lseek ( file, -8, SEEK_END );
   if ( offset == -1 )
   {
      exitError ( argv [ 1 ], "seeking" );
   }
   num_bytes = read ( file, ( void* ) integer, 4 );
   long length = *((long*)integer);
   if ( length < 0 ) // <=0 ??
   {
      exitNoHiddenFileError( argv [ 1 ], "Hidden data length < 0" );
   }
   offset = lseek ( file, -8, SEEK_END );
   offset = lseek ( file, (length * -1), SEEK_CUR );
   if ( offset == -1 )
   {
      exitNoHiddenFileError( argv [ 1 ], "Error seeking to hidden data" );
   }
   while (((( filesize < length ) &&
            ( num_bytes = read ( file, ( void* ) buffer, sizeof ( buffer ))) != -1) &&
            ( num_bytes != 0 )))
   {
      for ( i = 0; i < num_bytes; i++ )
      {
         if ( filesize < length )
         {
            buffer [ i ]--;
            filesize++;
         }
      }
      printf ( "%s", buffer);
   }
	return 0; // success
}
